package com.xhsj.user.hr.process.base;

import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.google.common.base.Joiner;
import com.xhsj.user.hr.base.BaseEntity;
import com.xhsj.user.hr.base.BaseService;
import com.xhsj.user.hr.process.dto.processDefinition.HandleAuditDto;
import com.xhsj.user.hr.process.hrLeaveProcess.query.FirstProcessNodeIdQuery;
import com.xhsj.user.hr.process.processDefinition.entity.TbGlobalApprovalHiTask;
import com.xhsj.user.hr.process.processDefinition.entity.TbGlobalApprovalTask;
import com.xhsj.user.hr.process.processDefinition.entity.TbGlobalWorkFlowNode;
import com.xhsj.user.hr.process.processDefinition.mapper.TbGlobalApprovalHiTaskMapper;
import com.xhsj.user.hr.process.processDefinition.mapper.TbGlobalApprovalTaskMapper;
import com.xhsj.user.hr.process.processDefinition.mapper.TbGlobalWorkFlowNodeMapper;
import com.xhsj.user.hr.process.processDefinition.query.ProcessNodeQuery;
import com.xhsj.user.hr.process.processDefinition.service.TbGlobalApprovalHiTaskService;
import com.xhsj.user.hr.process.processDefinition.service.TbGlobalApprovalTaskService;
import com.xhsj.user.hr.process.processDefinition.service.TbGlobalWorkFlowNodeService;
import com.xhsj.user.security.entity.LoginUser;
import com.xhsj.user.hr.system.mapper.TbGlobalRoleMapper;
import com.xhsj.user.hr.system.mapper.TbGlobalUserMapper;
import com.xhsj.user.utils.StringUtils;
import com.xhsj.user.utils.UserUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.*;

/**
 * @Description BaseProcessService
 * @Author suxiaolin
 * @Date 2020/11/4 16:30
 */
@Slf4j
public abstract class BaseProcessService<M extends BaseMapper<T>, T extends BaseEntity<T>> extends BaseService<M,T> {

    // 用户
    @Autowired
    private TbGlobalUserMapper tbGlobalUserMapper;

    // 角色
    @Autowired
    private TbGlobalRoleMapper tbGlobalRoleMapper;

    // 流程节点
    @Autowired
    private TbGlobalWorkFlowNodeMapper processNodeMapper;
    @Autowired
    private TbGlobalApprovalTaskMapper dao;

    // 流程历史
    @Autowired
    private TbGlobalApprovalHiTaskMapper processHiTaskMapper;

    @Autowired
    private TbGlobalApprovalTaskService tbGlobalApprovalTaskService;

    // 流程节点
    @Autowired
    private TbGlobalWorkFlowNodeService tbGlobalWorkFlowNodeService;

    // 流程历史
    @Autowired
    private TbGlobalApprovalHiTaskService processHiTaskService;


    // 公共开始流程
    public ProcessNodeQuery startHandleAudit(HandleAuditDto data, Long organizationId) throws Exception {
        // 得到节点id和几点名称
        ProcessNodeQuery processNodeVo = new ProcessNodeQuery();
        // 中deal_with字段 0 通过 1 退回 2 重要
        try {
            // 当前用户的角色id
            List<Long> roleListByUserId = tbGlobalRoleMapper.getRoleListByUserId(data.getCreateBy());
            // 查询初始流程节点
            List<FirstProcessNodeIdQuery> firstProcessNodeIdQuery= processNodeMapper.firstProcessNodeId(data.getApplyType(),organizationId);
            if (firstProcessNodeIdQuery.size() == 0) {
                throw new Exception("此部门下无流程节点,请联系管理员添加流程");
            }
            Object nextNodeId = null;
            Object roleId = null;
            String nodeName = null;
            String currenNnodeName = null;
            Long currentNodeId = null;
            for (FirstProcessNodeIdQuery firstProcessNodeId :firstProcessNodeIdQuery) {
                if (roleListByUserId.contains(firstProcessNodeId.getRoleId())) {
                    nextNodeId = firstProcessNodeId.getNextNodeId();
                    roleId = firstProcessNodeId.getNextRoleId();
                    nodeName = firstProcessNodeId.getNextNodeName();
                    currenNnodeName = firstProcessNodeId.getNodeName();
                    currentNodeId = firstProcessNodeId.getNodeId();
                    data.setBusinessId(firstProcessNodeId.getBusinessId());
                    break;
                }
                if (StringUtils.isNull(firstProcessNodeId.getRoleId())) {
                    nextNodeId = firstProcessNodeId.getNextNodeId();
                    roleId = firstProcessNodeId.getNextRoleId();
                    nodeName = firstProcessNodeId.getNextNodeName();
                    currenNnodeName = firstProcessNodeId.getNodeName();
                    currentNodeId = firstProcessNodeId.getNodeId();
                    data.setBusinessId(firstProcessNodeId.getBusinessId());
                }
            }
            if (roleId == null) {
                throw new Exception("此部门下无流程节点,请联系管理员添加流程");
            }
            data.setRoleIds(Arrays.asList(String.valueOf(roleId).split(",")));
            processNodeVo.setRoleIds(data.getRoleIds());
            // 获取下一个节点的用户名
            String handler = this.getHandler(data);
            TbGlobalApprovalTask processTask = null;
            // 角色
            if (!Objects.isNull(data.getRoleIds())) {
                List<Long> split1 = JSONArray.parseArray(String.valueOf(data.getRoleIds()), Long.class);
                for (Long s : split1) {
                    // 审核参数转正在执行流程表参数
                    data.setRoleIds(null);
                    processTask = StringUtils.toJavaBean(data, TbGlobalApprovalTask.class);
                    processTask.setRoleId(s);
                    processTask.setNodeId(StringUtils.toLong(nextNodeId));
                    processTask.setHandler(handler);
                    // 添加正在执行任务+保存当前节点历史记录+下一个节点的历史记录
                    this.startSavaCurrentRunAndHisTask(processTask,data.getOpinionText(),currenNnodeName,currentNodeId);
                    this.savaRunAndHisTask(processTask,data.getOpinionText(),nodeName);
                }
            }

            LoginUser loginAppUser = UserUtils.getLoginAppUser();
            processNodeVo.setCurrentUserId(loginAppUser.getUserId());
            processNodeVo.setNodeId(StringUtils.toLong(nextNodeId));
            processNodeVo.setNodeName(nodeName);
        } catch (Exception e) {
            log.error("添加流程失败", e);
            throw new Exception(e);
        }
        return processNodeVo;
    }


    // 公共流程
    public ProcessNodeQuery handleAudit(HandleAuditDto data) throws Exception {
        // 得到节点id和几点名称
        ProcessNodeQuery processNodeVo = new ProcessNodeQuery();
        Object roleIds = null;
        Object auditUserId = null;
        // 中deal_with字段 0 通过 1 退回 2 重要
        try {
            Object nextNodeId =null;
            // 节点名称
            String nodeName = null;
            if (data.getStatus()== 1) {
                // 查询初始流程节点
                QueryWrapper queryWrapper = new QueryWrapper();
                queryWrapper.eq("business_id",data.getBusinessId());
                queryWrapper.eq("approve_order_no",1);
                TbGlobalWorkFlowNode firstProcessNodeIdQuery = tbGlobalWorkFlowNodeService.getOne(queryWrapper);
                nextNodeId = firstProcessNodeIdQuery.getApproveOrderNo();
                nodeName = firstProcessNodeIdQuery.getTaskName();
                data.setUserId(Arrays.asList(String.valueOf(data.getProposerId()).split(",")));
            }else if(data.getStatus()== 0){
                // 查询下一节点
                Map<String, Object> map = getNextNode(data.getNodeId(),data.getBusinessId());
                nextNodeId = map.get("nextNodeId");
                Object roleId = map.get("roleId");
                if (!Objects.isNull(roleId)) {
                    data.setRoleIds(Arrays.asList(String.valueOf(roleId).split(",")));
                }
                nodeName = String.valueOf(map.get("nextNodeName"));
            }
            // 获取下一个节点的用户名
            String handler = this.getHandler(data);
            TbGlobalApprovalTask processTask = null;
            if (!Objects.isNull(nextNodeId) && StringUtils.isNotBlank(nextNodeId)) {
                // 用户
                if (!Objects.isNull(data.getUserId())) {
                    auditUserId = data.getUserId();
                    List<Long> split = JSONArray.parseArray(String.valueOf(data.getUserId()), Long.class);
                    for (Long s : split) {
                        // 审核参数转正在执行流程表参数
                        data.setUserId(null);
                        processTask = StringUtils.toJavaBean(data, TbGlobalApprovalTask.class);
                        processTask.setUserId(s);
                        processTask.setNodeId(StringUtils.toLong(nextNodeId));
                        processTask.setHandler(handler);
                        // 添加下一个节点执行任务
                        this.savaRunAndHisTask(processTask,data.getOpinionText(),nodeName);
                    }
                }
                // 角色
                if (!Objects.isNull(data.getRoleIds())) {
                    roleIds = data.getRoleIds();
                    List<Long> split1 = JSONArray.parseArray(String.valueOf(data.getRoleIds()), Long.class);
                    for (Long s : split1) {
                        // 审核参数转正在执行流程表参数
                        data.setRoleIds(null);
                        processTask = StringUtils.toJavaBean(data, TbGlobalApprovalTask.class);
                        processTask.setRoleId(s);
                        processTask.setNodeId(StringUtils.toLong(nextNodeId));
                        processTask.setHandler(handler);
                        // 添加正在执行任务
                        this.savaRunAndHisTask(processTask,data.getOpinionText(),nodeName);
                    }
                }
            }

            long nodeId = StringUtils.toLong(nextNodeId);
            if ("完结".equals(nodeName)) { // 将完结节点添加到历史表
                Long userId = UserUtils.getLoginAppUser().getUserId();
                TbGlobalApprovalHiTask tbGlobalApprovalHiTask = new TbGlobalApprovalHiTask(data.getBusinessId(),data.getDataId(),nodeId,0,nodeName,userId,new Date(),userId,new Date());
                processHiTaskService.save(tbGlobalApprovalHiTask);
            }
            // 修改目前执行的任务+保存意见
            updateRunTask(data);
            // 节点id
            LoginUser loginAppUser = UserUtils.getLoginAppUser();
            Long userId = loginAppUser.getUserId();
            processNodeVo.setRoleIds(data.getRoleIds());
            processNodeVo.setUserId(data.getUserId());
            processNodeVo.setCurrentUserId(userId);
            processNodeVo.setNodeId(nodeId);
            processNodeVo.setUserId(auditUserId);
            processNodeVo.setRoleIds(roleIds);
            processNodeVo.setNodeName(nodeName);
            if (data.getStatus()== 3){
                processNodeVo.setNodeName("作废");
                processNodeVo.setNodeId(0);
                processNodeVo.setDelFlag(1);
            }
        } catch (Exception e) {
            log.error("添加流程失败", e);
            throw new Exception(e);
        }
        return processNodeVo;
    }

    // 修改目前执行的任务
    public void updateRunTask(HandleAuditDto data) throws Exception {
        // 修改目前执行的任务
        if (StringUtils.isNotBlank(data.getProcessTaskId())) {
            Long s = data.getProcessTaskId();
            // 删除正在执行任务
            int row1 = dao.deleteTaskById(s);
            if (row1 == 0) {
                log.error("保存数据失败");
                throw new Exception("保存数据失败");
            }
            // 修改历史表处理人+保存意见
            updateHiTask(data);
        }
    }

    // 修改目前执行的任务
    private void updateHiTask(HandleAuditDto data) throws Exception {
        Long s = data.getProcessTaskId();
        // 修改历史表处理人
        TbGlobalApprovalHiTask processHiTask = new TbGlobalApprovalHiTask();
        processHiTask.setId(s);
        processHiTask.setUserId(UserUtils.getLoginAppUser().getUserId());
        processHiTask.setHandler(UserUtils.getLoginAppUser().getFullName());
        processHiTask.setRoleId(null);
        processHiTask.setUpdateDate(new Date());
        processHiTask.setOpinionText(data.getOpinionText());
        processHiTask.setStatus(data.getStatus());
        boolean update = processHiTaskService.updateById(processHiTask);
        if (!update) {
            log.error("保存数据失败");
            throw new Exception("保存数据失败");
        }
    }

    // 当前节点下一个节点相关的数据
    public Map<String, Object> getNextNode(long nodeId,long businessId) {
        return  processNodeMapper.getNextNode(nodeId,businessId);
    }


    // 获取下一个节点的用户名
    public String getHandler(HandleAuditDto data) throws Exception {
        // 获取下一个节点的用户名根据用户ids
        Set<String> fullNamesByUserId = new HashSet<>();
        if (StringUtils.isNotBlank(data.getUserId())) {
            List<String> userIdList = JSONArray.parseArray(String.valueOf(data.getUserId()), String.class);
            fullNamesByUserId = tbGlobalUserMapper.getFullNameByUserIds(userIdList);
        }
        // 获取下一个节点的用户名根据角色ids
        Set<String> fullNamesByRoleId = new HashSet<>();
        if (StringUtils.isNotBlank(data.getRoleIds())) {
            List<String> roleIdList = JSONArray.parseArray(String.valueOf(data.getRoleIds()), String.class);
            fullNamesByRoleId = tbGlobalUserMapper.getFullNameByRoleIds(roleIdList);
        }
        fullNamesByUserId.addAll(fullNamesByRoleId);
        String handler = Joiner.on(",").join(fullNamesByUserId);
        return handler;
    }

    // 添加当前执行任务到历史任务
    private void startSavaCurrentRunAndHisTask(TbGlobalApprovalTask processTask,String opinionText,String currenNnodeName,Long currentNodeId) throws Exception {
        LoginUser loginAppUser = UserUtils.getLoginAppUser();
        TbGlobalApprovalHiTask processHiTask = new TbGlobalApprovalHiTask();
        BeanUtils.copyProperties(processTask,processHiTask);
        processHiTask.setStatus(0);// 已审核
        processHiTask.setCreateBy(processHiTask.getCreateBy());
        processHiTask.setOpinionText(opinionText);
        processHiTask.setUserId(processHiTask.getCreateBy());
        processHiTask.setHandler(loginAppUser.getFullName());
        processHiTask.setRoleId(null);
        processHiTask.setNodeId(currentNodeId);
        processHiTask.setNodeName(currenNnodeName);
        processHiTask.setCreateBy(processHiTask.getCreateBy());
        processHiTask.setCreateDate(new Date(System.currentTimeMillis() - 1000));
        processHiTask.setUpdateDate(processHiTask.getCreateDate());
        int insert = processHiTaskMapper.insert(processHiTask);
        if (insert == 0) {
            log.error("添加当前执行任务到历史任务失败");
            throw new Exception("添加当前执行任务到历史任务失败");
        }
    }

    // 保存下一个流程指派人和正在执行任务到历史任务
    public void savaRunAndHisTask(TbGlobalApprovalTask processTask,String opinionText,String nodeName) throws Exception {
        // 保存下一个流程指派人
        boolean saveTask = tbGlobalApprovalTaskService.save(processTask);
        if (!saveTask) {
            log.error("保存数据失败");
            throw new Exception("保存数据失败");
        }
        // 添加正在执行任务到历史任务
        if (processTask !=null) {
            TbGlobalApprovalHiTask processHiTask = new TbGlobalApprovalHiTask();
            BeanUtils.copyProperties(processTask,processHiTask);
            processHiTask.setStatus(2);// 未审核
            processHiTask.setUpdateDate(processHiTask.getCreateDate());
            processHiTask.setUpdateBy(processHiTask.getCreateBy());
            processHiTask.setNodeName(nodeName);
            int insert = processHiTaskMapper.insert(processHiTask);
            if (insert == 0) {
                log.error("保存数据失败");
                throw new Exception("保存数据失败");
            }
        }
    }

}
